Если вы хотите извлечь данные из веб-страниц с помощью Python, XPath — это важный инструмент, который должен быть в вашем наборе инструментов для парсинга веб-страниц. XPath предоставляет возможность перемещаться по HTML-структуре страницы и точно определять нужные элементы и данные.
В этом руководстве мы рассмотрим основы XPath и продемонстрируем, как вы можете использовать его возможности для парсинга веб-страниц с помощью Python. К концу вы будете готовы решать широкий спектр задач по очистке данных, используя XPath для хирургического извлечения нужных вам данных.
Что такое XPath?
XPath означает язык XML Path. Это язык запросов для выбора узлов из документа XML или HTML. С помощью XPath вы указываете шаблон, соответствующий структуре документа, и он возвращает все элементы, соответствующие этому шаблону.
Хотя XPath изначально был разработан для XML, он так же хорошо работает с HTML, что делает его идеальным для целей веб-скрапинга. Он предоставляет более мощную и гибкую альтернативу селекторам CSS или регулярным выражениям.
Основы синтаксиса XPath
Чтобы начать использовать XPath, вам необходимо понять строительные блоки синтаксиса XPath. Вот ключевые понятия:
Выбор узлов по имени тега
Самое простое выражение XPath — просто указать имя тега. Например:
//h1
выбирает все<h1>
элементы заголовка на странице//p
выбирает все<p>
элементы абзаца//img
выбирает все<img>
элементы изображения
Выбор узлов по атрибуту
Вы можете выбрать элементы, имеющие определенный атрибут или значение атрибута, используя @
синтаксис:
//*[@class="highlighted"]
выбирает все элементы, у которых класс «выделен»//a[@href]
выбирает все<a>
элементы привязки, имеющие атрибут href//img[@alt="Logo"]
выбирает<img>
элементы с альтернативным текстом «Логотип»
Выбор узлов по положению
Вы можете выбирать узлы в зависимости от их положения, используя квадратные скобки. []
и числовой индекс:
//ul/li[1]
выбирает первый<li>
элемент внутри каждого<ul>
неупорядоченный список//table/tr[last()]
выбирает последний<tr>
строка в каждом<table>
//ol/li[position() <= 3]
выбирает первые три<li>
предметы в каждом<ol>
упорядоченный список
Выбор узлов по отношению
XPath позволяет перемещаться вверх и вниз по дереву документа, чтобы выбирать элементы на основе их предков, потомков, братьев и сестер и т. д.:
//div[@class="content"]/*
выбирает все дочерние элементы<div>
элементы с классом «контент»//p/..
выбирает родительские элементы всех<p>
пункты//h1/following-sibling::p
выбирает все<p>
элементы, которые являются братьями и сестрами после<h1>
Заголовок//section//img
выбирает все<img>
элементы, являющиеся потомками<section>
на любом уровне
Предикаты и функции
XPath поддерживает широкий спектр предикатов и функций для дальнейшего уточнения вашего выбора:
//p[contains(text(),"scrapy")]
выбирает<p>
элементы, содержащие текст «скрапи»//a[starts-with(@href,"https")]
выбирает<a>
элементы, у которых href начинается с «https»//ul[count(li) > 10]
выбирает<ul>
элементы, содержащие более 10<li>
пункты//img[string-length(@alt) > 0]
выбирает<img>
элементы с непустым атрибутом alt
Использование XPath с lxml и BeautifulSoup
Теперь, когда вы понимаете основы синтаксиса XPath, давайте посмотрим, как его можно использовать в Python с популярными библиотеками lxml и BeautifulSoup. Мы рассмотрим пример очистки текста основного заголовка с домашней страницы ScrapingBee.
Анализ HTML с помощью lxml и BeautifulSoup
Во-первых, нам нужно получить HTML-код веб-страницы с помощью библиотеки запросов и проанализировать его в древовидную структуру, которую мы можем запросить с помощью XPath. Мы будем использовать BeautifulSoup для анализа HTML и lxml для оценки наших выражений XPath:
import requests
from bs4 import BeautifulSoup
from lxml import etree
html = requests.get("https://scrapingbee.com")
soup = BeautifulSoup(html.text, "html.parser")
dom = etree.HTML(str(soup))
Мы тут:
- Получите HTML, используя
requests.get()
- Разберите строку HTML в объект BeautifulSoup, используя html.parser.
- Преобразуйте объект BeautifulSoup в строку, чтобы мы могли проанализировать его с помощью lxml.
etree.HTML()
функция - Разобрать строку в lxml
Element
объект, который мы можем запросить с помощью XPath
Создание и оценка выражений XPath
Теперь, когда у нас есть проанализированное дерево HTML, мы можем создать выражение XPath для выбора основного <h1>
заголовок на странице:
heading_xpath = ‘//h1‘
Чтобы сравнить этот XPath с нашим проанализированным HTML-документом, мы используем метод xpath()
Метод:
heading_elements = dom.xpath(heading_xpath)
Ассоциация dom.xpath()
вызов вернет список всех элементов, соответствующих нашему селектору XPath. В этом случае должно быть только одно совпадение. <h1>
элемент.
Извлечение текста и атрибутов
Получив ссылку на элемент, мы можем легко извлечь его текст и любые атрибуты, используя свойства lxml:
heading_text = heading_elements[0].text
print(heading_text)
# Tired of getting blocked while scraping the web?
Мы успешно извлекли текст заголовка с помощью всего лишь одной строки XPath! Мы также могли бы получить доступ к значениям атрибутов элемента, используя get()
:
heading_id = heading_elements[0].get(‘id‘)
Использование XPath с Selenium
Альтернативный подход — использовать Selenium для автоматизации и очистки динамических веб-сайтов, требующих JavaScript. Selenium предоставляет собственные методы для выбора элементов с помощью строк XPath.
Настройка Selenium WebDriver
Чтобы начать работу с Selenium, сначала необходимо установить пакет Selenium и веб-драйвер для браузера, который вы хотите использовать. Вот как вы можете настроить драйвер Chrome:
from selenium import webdriver
from selenium.webdriver.common.by import By
driver_path = "/path/to/chromedriver"
driver = webdriver.Chrome(driver_path)
Обязательно загрузите соответствующую версию ChromeDriver для вашей установки Chrome и укажите путь к исполняемому файлу.
Поиск элементов с помощью XPath
Настроив драйвер, мы можем перейти на веб-страницу и начать поиск элементов. WebDriver Selenium предоставляет find_element
метод, который принимает локатор XPath:
driver.get("https://scrapingbee.com")
heading_xpath = "//h1"
heading_element = driver.find_element(By.XPATH, heading_xpath)
Как и в примере с lxml, здесь будет найден первый <h1>
элемент на странице. Если вы хотите найти все элементы, соответствующие XPath, используйте find_elements
вместо:
paragraph_xpath = "//p"
paragraph_elements = driver.find_elements(By.XPATH, paragraph_xpath)
Извлечение текста и атрибутов
Имея ссылку на веб-элемент, вы можете получить доступ к его свойствам, таким как текстовое содержимое и атрибуты:
heading_text = heading_element.text
print(heading_text)
# Tired of getting blocked while scraping the web?
paragraph_id = paragraph_elements[0].get_attribute("id")
Извлечение данных с помощью Selenium и XPath довольно простое, но имейте в виду, что Selenium обычно работает медленнее, чем использование простой библиотеки HTTP-запросов, поскольку он запускает настоящий браузер.
Советы и рекомендации
Когда вы начнете использовать XPath для парсинга веб-страниц, вам следует запомнить несколько советов и рекомендаций:
Используйте Chrome DevTools для тестирования выражений XPath
При создании селекторов XPath очень полезно протестировать их в интерактивном режиме, чтобы убедиться, что они соответствуют вашим ожиданиям. Chrome DevTools предоставляет простой способ сделать это:
- Щелкните элемент правой кнопкой мыши и выберите «Проверить», чтобы открыть панель «Элементы DevTools».
- Нажмите Ctrl+F, чтобы открыть окно поиска.
- Введите выражение XPath, чтобы выделить соответствующие элементы на странице.
Обработка противоречивой разметки
Веб-сайты часто имеют противоречивую или неправильную HTML-разметку, которая может сбить с толку ваши селекторы XPath. Рекомендуется использовать такую библиотеку, как BeautifulSoup, для очистки и нормализации HTML перед его анализом с помощью lxml.
Напишите надежный и удобный в обслуживании XPath
Чтобы свести к минимуму вероятность поломки вашего парсера из-за изменений макета на целевом сайте, постарайтесь писать выражения XPath как можно более конкретными, но не более конкретными, чем необходимо. Отдавайте предпочтение выбору по семантическим свойствам, таким как имена тегов, идентификаторы и атрибуты данных, а не полагаясь на конкретную структуру разметки.
Также неплохо разбить сложные выражения XPath на переменные с описательными именами, чтобы улучшить читаемость и удобство обслуживания.
Кэшируйте результаты для повышения производительности
Если вы очищаете большие объемы данных или несколько раз посещаете одни и те же страницы, рассмотрите возможность кэширования результатов анализа HTML и XPath, чтобы избежать ненужных сетевых запросов и накладных расходов на анализ. Для кэширования вы можете использовать простой словарь или более надежное решение, такое как MongoDB или Redis.
Заключение
XPath — невероятно мощный инструмент для точного извлечения данных из HTML-страниц. Обладая базовым пониманием синтаксиса и способностью переводить селекторы CSS в их эквиваленты XPath, вы сможете выполнять широкий спектр задач по очистке веб-страниц.
Библиотеки Python, такие как lxml, BeautifulSoup и Selenium, предоставляют простые способы интеграции XPath в ваши рабочие процессы парсинга. В зависимости от ваших конкретных потребностей и характеристик целевого сайта вы можете выбрать наиболее подходящий подход.
Продолжая парсинг веб-страниц с помощью Python и XPath, всегда соблюдайте условия обслуживания веб-сайта и ограничения файла robots.txt. И не забудьте освежить в памяти основы функций и операторов XPath — вы будете поражены тем, как многого можно достичь с помощью всего лишь нескольких строк умного XPath!